package com.zh.common.view

import android.content.Context
import android.graphics.*
import android.text.TextPaint
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import com.zh.common.R
import com.zh.common.ktx.dp2px
import com.zh.common.ktx.sp2px

/**
 * 角标 - 小红点
 * 默认最大 99
 */
class BadgeView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    // 小红点真实大小 比 文本 的margin(不包括白边)
    private val BADGE_TEXT_MARGIN_LEFT = 5f.dp2px
    private val BADGE_TEXT_MARGIN_TOP = 3f.dp2px
    private val BADGE_TEXT_MARGIN_RIGHT = 5f.dp2px
    private val BADGE_TEXT_MARGIN_BOOTOM = 3f.dp2px

    ////可设置部分 start///////////////////////////////////////////////
    // 未读数; 在显示的时候 未读数默认显示形式9/23/99+
    private var badgeNumber = 0
    private var maxNumber = 0
    private var badgeBackgroundColor = 0
    private var badgeNumColor = 0
    private var badgeNumSize = 0f

    // 是否显示数字, 默认显示小红点
    private var showNum = false

    // 不显示数字时, 小红点的大小
    private var badgeRedSize = 0f

    // 有些设计要求未读前面加"+", (至少我们设计师这么设计) 显示成 +1/+34/+99
    private var badgeNumPre: String? = null

    ////可设置部分 end///////////////////////////////////////////////
    ////以下是辅助变量///////////////////////////////////////////////
    // badge的整体宽高
    private var badgeHeight = 0f
    private var badgeWidth = 0f

    // badgeNum/小红点 的真实宽高
    private var badgeNumHeight = 0f
    private var badgeNumWidth = 0f

    // 未读数显示的文案; 未读数默认显示形式9/23/99+
    private var showUneadText: String? = null

    // 画笔
    private var contentPaint: Paint = Paint()
    private var badgeNumPaint: TextPaint = TextPaint()

    init {
        val array = context.obtainStyledAttributes(attrs, R.styleable.BadgeView)
        badgeNumber = array.getInteger(R.styleable.BadgeView_bv_badgeNumber, 0)
        maxNumber = array.getInt(R.styleable.BadgeView_bv_maxNumber, 99)
        badgeBackgroundColor =
            array.getColor(R.styleable.BadgeView_bv_backgroundColor, Color.RED)
        badgeNumColor = array.getColor(R.styleable.BadgeView_bv_badgeNumberColor, Color.WHITE)
        badgeNumSize =
            array.getDimension(R.styleable.BadgeView_bv_badgeNumberSize, 12f.sp2px.toFloat())
        showNum = array.getBoolean(R.styleable.BadgeView_bv_showNumber, true)
        badgeRedSize =
            array.getDimension(R.styleable.BadgeView_bv_badgeRedSize, 6f.dp2px.toFloat())
        badgeNumPre = array.getString(R.styleable.BadgeView_bv_badgeNumPre)

        // 初始化badgeNum的画笔
        badgeNumPaint.isAntiAlias = true
        badgeNumPaint.color = badgeNumColor
        badgeNumPaint.textSize = badgeNumSize
        badgeNumPaint.textAlign = Paint.Align.CENTER
        // 计算 未读数的高度
        val minBadge = getUnreadText(0)
        val minBadgeRect = Rect()
        badgeNumPaint.getTextBounds(minBadge, 0, minBadge.length, minBadgeRect)
        // 计算badge的高度
        badgeNumHeight = minBadgeRect.height().toFloat()
        badgeHeight = badgeNumHeight + BADGE_TEXT_MARGIN_TOP + BADGE_TEXT_MARGIN_BOOTOM
        // 限制设置小红点的大小不能超过数字显示模式; 显示在文字模式大小的左下角
        if (badgeRedSize > badgeNumHeight + BADGE_TEXT_MARGIN_TOP + BADGE_TEXT_MARGIN_BOOTOM) {
            badgeRedSize = badgeNumHeight + BADGE_TEXT_MARGIN_TOP + BADGE_TEXT_MARGIN_BOOTOM
        }
        //关闭清空TypedArray
        array.recycle()
        contentPaint.isAntiAlias = true
    }

    fun setNumber(badgeNum: Int) {
        this.badgeNumber = badgeNum
        // 需要重新计算高宽,所以用这个
        requestLayout()
    }

    fun getNumber(): Int {
        return badgeNumber
    }

    fun setShowNum(isShow: Boolean) {
        showNum = isShow
        // 需要重新计算高宽,所以用这个
        requestLayout()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (badgeNumber > 0) {
            canvas.save()
            oDrawBadge(canvas)
            canvas.restore()
        }
    }

    private fun oDrawBadge(canvas: Canvas) {
        contentPaint.color = badgeBackgroundColor
        contentPaint.style = Paint.Style.FILL
        if (showNum) {
            // 绘制红色背景图
            val path = Path()
            path.addArc(RectF(0f, 0f, badgeHeight, badgeHeight), 90f, 180f)
            path.lineTo(badgeWidth - badgeHeight / 2, 0f)
            path.addArc(
                RectF(
                    badgeWidth - badgeHeight, 0f, badgeWidth, badgeHeight
                ), 270f, 180f
            )
            path.lineTo(badgeHeight / 2, badgeHeight)
            canvas.drawPath(path, contentPaint)
            // 写上数字
            canvas.drawText(
                showUneadText!!, badgeWidth / 2,
                badgeHeight - BADGE_TEXT_MARGIN_BOOTOM, badgeNumPaint
            )
        } else {
            // 画实心圆
            canvas.drawCircle(
                badgeRedSize / 2, badgeHeight * 2 / 3 - badgeRedSize / 2,
                badgeRedSize / 2, contentPaint
            )
        }
    }

    /**
     * 构造未读数显示的文本
     * 1) 未读数默认显示形式9/23/99+
     * 2) 有些设计要求未读前面加"+", (至少我们设计师这么设计) 显示成 +1/+34/+99, 取配置badgeNumPre
     * @param unread
     * @return
     */
    private fun getUnreadText(unread: Int): String {
        var text = unread.toString()
        if (TextUtils.isEmpty(badgeNumPre)) {
            if (unread > maxNumber) {
                text = "$maxNumber+"
            }
        } else {
            if (unread > maxNumber) {
                text = badgeNumPre + "maxNumber"
            } else if (unread >= 0) {
                text = badgeNumPre + unread
            }
        }
        return text
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        // 初始化Badge的数据
        if (showNum) {
            showUneadText = getUnreadText(badgeNumber)
            val badgeRect = Rect()
            badgeNumPaint.getTextBounds(showUneadText, 0, showUneadText!!.length, badgeRect)
            badgeNumWidth = badgeRect.width().toFloat()
            badgeWidth = if (showUneadText!!.length == 1) {
                // 当长度为1的时候,显示正圆
                badgeHeight
            } else {
                badgeNumWidth + BADGE_TEXT_MARGIN_LEFT + BADGE_TEXT_MARGIN_RIGHT
            }
        } else {
            badgeWidth = badgeRedSize
        }
        setMeasuredDimension(badgeWidth.toInt(), badgeHeight.toInt())
    }
}